package com.roadmap.client.module.task;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import com.roadmap.common.BaseUtility;
import com.roadmap.common.RdcLogger;
import com.roadmap.common.BaseEnum.TimeType;
import com.roadmap.entities.LifeTask;
import com.roadmap.exception.InvalidQueryException;
import com.roadmap.exception.InvalidValueException;
import com.roadmap.exception.NullObjectException;
import com.roadmap.exception.ServerException;
import com.roadmap.repo.db.DatabaseUtility;
import com.roadmap.repo.db.IDatabaseUtility;

public class TaskProgress implements ITaskProgress {
	private final IDatabaseUtility dbUtil = new DatabaseUtility();
	private final static Logger logger = RdcLogger
			.getLogger(TaskProgress.class);

	/**
	 * firstly get all execution records of the task from the database and then
	 * summarize all of them
	 */
	public int getActualProgress(LifeTask task) throws NullObjectException,
			InvalidQueryException, InvalidValueException, ServerException {
		popNullObjectException(task);

		int progress = 0;
		String sql = "select sum(proportionOfTask) from execution where taskId='"
				+ task.getId() + "'";
		List list = dbUtil.queryBySQL(sql);
		if (list != null && list.size() > 0) {
			Object obj = list.get(0);
			if (obj != null)
				progress = ((BigDecimal) obj).intValue();
		}

		return progress;

		// StringBuffer criteria = new StringBuffer("taskId='");
		// criteria.append(task.getId());
		// criteria.append("'");
		// List execs = dbUtil.getEntitiesByCriteria(Execution.class, criteria
		// .toString());
		// Iterator iter = execs.iterator();
		// int total = 0;
		// while (iter.hasNext()) {
		// Execution exec = (Execution) iter.next();
		// total += exec.getProportionOfTask();
		// logger.debug("execution proporation: " + total);
		// }

		// return total;
	}

	/**
	 * returned value = the progress a task's executions finished multiples the
	 * task's proportion in its plan
	 */
	public int getActualProgressInPlan(LifeTask task)
			throws NullObjectException, InvalidQueryException,
			InvalidValueException, ServerException {
		int pro = getActualProgress(task);
		int proInPlan = task.getProportionOfGoal();
		logger.debug("task proporation in plan: " + proInPlan);
		return pro * proInPlan / 100;
	}

	/***/
	public int getIdealProgress(LifeTask task) throws NullObjectException,
			InvalidQueryException, InvalidValueException, ServerException {
		popNullObjectException(task);

		Date start = task.getScheduledStartDate();
		Date end = task.getScheduledEndDate();
		if (start.after(end)) {
			InvalidValueException ive = new InvalidValueException(
					"Wrong data in database. The start date should be before the end date.");
			logger.error(ive);
			throw ive;
		}

		Date today = new Date();
		// if the task is scheduled to start in a future date
		if (today.before(start))
			return 0;
		else {
			if (start.equals(end))
				return 100;
			int proInPlan = task.getProportionOfGoal();
			int days = BaseUtility.getTimeDiffBetween(end, start, TimeType.DAY);
			int todays = BaseUtility.getTimeDiffBetween(today, start,
					TimeType.DAY);
			float pro = (1.0f * proInPlan) * todays / days;
			return (int) pro;
		}
	}

	/**
	 * returned value = the ideal progress of a task multiples the task's
	 * proportion in its plan
	 */
	public int getIdealProgressInPlan(LifeTask task)
			throws NullObjectException, InvalidQueryException,
			InvalidValueException, ServerException {
		int pro = getIdealProgress(task);
		int proInPlan = task.getProportionOfGoal();
		return pro * proInPlan / 100;
	}
	
	private void popNullObjectException(LifeTask task) throws NullObjectException{
		if (task == null || task.getId() == null) {
			NullObjectException noe = new NullObjectException(
					);
			logger.error("the entity can't be NULL", noe);
			throw noe;
		}
	}

}
